package com.linxuan.reggie.service.impl;

import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.linxuan.reggie.dao.SetmealMapper;
import com.linxuan.reggie.dto.DishDto;
import com.linxuan.reggie.dto.SetmealDto;
import com.linxuan.reggie.entity.Dish;
import com.linxuan.reggie.entity.Setmeal;
import com.linxuan.reggie.entity.SetmealDish;
import com.linxuan.reggie.service.DishService;
import com.linxuan.reggie.service.SetmealDishService;
import com.linxuan.reggie.service.SetmealService;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.io.File;
import java.util.List;
import java.util.stream.Collectors;

/**
 * 添加事务注解，开启事务这样添加套餐和添加套餐与菜品关系表会同时成功
 */
@Service
@Slf4j
@Transactional
public class SetmealServiceImpl extends ServiceImpl<SetmealMapper, Setmeal> implements SetmealService {

    @Autowired
    private SetmealDishService setmealDishService;

    @Autowired
    private DishService dishService;

    @Value("${reggie.path}")
    private String basePath;

    /**
     * 新增套餐，同时要保持与菜品的关联关系
     *
     * @param setmealDto 使用Dto来接收前端传过来的参数
     */
    @Override
    public void saveWithDish(SetmealDto setmealDto) {
        // 操作套餐表，添加套餐信息
        this.save(setmealDto);

        // 获取该套餐所包含的所有菜品
        List<SetmealDish> setmealDishes = setmealDto.getSetmealDishes();
        // 这些菜品都没有设置与之对应的套餐ID，这里设置一下
        setmealDishes.forEach((item) -> {
            item.setSetmealId(setmealDto.getId());
        });
        // 操作套餐菜品关联表，保存两者关系
        setmealDishService.saveBatch(setmealDishes);
    }

    /**
     * 删除套餐，同时要删除菜品的关系以及图片
     *
     * @param id 需要删除套餐的ID
     */
    @Override
    public void removeWithDishImgById(String id) {

        // 首先删除图片。通过套餐id获取套餐信息，然后获取图片名称，最后判断是否需要删除
        Setmeal setmeal = this.getById(id);
        String image = setmeal.getImage();
        File file = new File(basePath + image);
        if (file.exists()) {
            log.info("图片存在，删除图片");
            file.delete();
        }

        // 在setmeal表中根据套餐ID删除信息
        this.removeById(id);

        // 创建条件构造器并添加条件
        LambdaQueryWrapper<SetmealDish> wrapper = new LambdaQueryWrapper<>();
        wrapper.eq(SetmealDish::getSetmealId, id);

        // 在setmeal_dish表里面删除setmeal_id = id的数据
        setmealDishService.remove(wrapper);
    }

    /**
     * 查询setmeal表以及setmeal_dish表数据组装至SetmealDto类里面
     *
     * @param id 需要查询的套餐ID
     * @return SetmealDto
     */
    @Override
    public SetmealDto getByIdWithDish(String id) {
        // 首先查询套餐表信息，查询出来套餐基本信息：套餐ID、套餐名称、套餐所属分类ID、套餐价格、套餐图片、套餐描述
        Setmeal setmeal = this.getById(id);
        // 然后将查询出来的数据都拷贝至setmealDto里面
        SetmealDto setmealDto = new SetmealDto();
        BeanUtils.copyProperties(setmeal, setmealDto);

        // 根据套餐ID查询套餐所关联的菜品信息
        LambdaQueryWrapper<SetmealDish> lambdaQueryWrapper = new LambdaQueryWrapper<>();
        lambdaQueryWrapper.eq(SetmealDish::getSetmealId, id);
        List<SetmealDish> list = setmealDishService.list(lambdaQueryWrapper);

        // 在SetmealDto里面设置查询到的套餐关联的菜品信息
        setmealDto.setSetmealDishes(list);

        return setmealDto;
    }

    /**
     * 更新套餐以及套餐关联菜品表
     *
     * @param setmealDto 前端传过来的SetmealDto数据类型
     */
    @Override
    public void updateWithDish(SetmealDto setmealDto) {

        // 更新套餐表信息
        this.updateById(setmealDto);

        // 更新套餐关联菜品表信息
        LambdaQueryWrapper<SetmealDish> lambdaQueryWrapper = new LambdaQueryWrapper<>();
        // 删除之前关联的菜品信息
        lambdaQueryWrapper.eq(SetmealDish::getSetmealId, setmealDto.getId());
        setmealDishService.remove(lambdaQueryWrapper);
        // 添加现在关联的菜品信息，这些菜品信息还没有添加上与之关联的套餐信息，所以需要添加套餐ID
        List<SetmealDish> setmealDishes = setmealDto.getSetmealDishes();
        setmealDishes.forEach((item) -> {
            item.setSetmealId(setmealDto.getId());
        });
        setmealDishService.saveBatch(setmealDishes);
    }

    /**
     * 根据套餐ID查询套餐关联的菜品详细数据并封装至DTO类型中
     * @param id 套餐ID
     * @return 返回套餐关联的菜品详细数据
     */
    @Override
    public List<DishDto> getDishDtoBySetmealId(String id) {
        // 构造查询条件，查询出来所有该套餐关联的菜品信息
        LambdaQueryWrapper<SetmealDish> setmealDishLambdaQueryWrapper = new LambdaQueryWrapper<>();
        setmealDishLambdaQueryWrapper.eq(id != null, SetmealDish::getSetmealId, id);
        List<SetmealDish> setmealDishList = setmealDishService.list(setmealDishLambdaQueryWrapper);

        List<DishDto> dishDtoList = setmealDishList.stream().map((item) -> {
            // 获取菜品dishID
            Long dishId = item.getDishId();
            // 查询菜品表 查询出来菜品详细信息
            Dish dish = dishService.getById(dishId);
            // 将查询出来的信息都封装至dishDto里面，例外将setmealDish(item)里面的份数也封装进去
            DishDto dishDto = new DishDto();
            BeanUtils.copyProperties(dish, dishDto);
            dishDto.setCopies(item.getCopies());
            // 将数据返回
            return dishDto;
        }).collect(Collectors.toList());

        // 数据返回
        return dishDtoList;
    }
}
